5-2 CGI 捊うУP

上節介紹了 CGI 的基本功能與原理,本節將介紹 CGI 如何由使用者取得表單資訊。

我們先以一個簡單的範例 (widget0.htm) 來說明:

Example(widget0.htm):

此範例包含了一個很簡單的表單,其原始碼如下:

原始檔(widget0.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
<TITLE>A Simple Form for CGI Programming</TITLE>
</head>

<body background="/jang/graphics/background/paper.jpg">
<h2 align=center>A Simple Form for CGI Programming</h2>
<hr>

<form method=get action="getCgiParam.pl">
<ul>
<li>大名:<input name="your_name" value="Roger Jordan & 大雄">
<li>性別:<input type="radio" name="gender" value="male">男
	<input type="radio" name="gender" value="female">女
	<input type="radio" name="gender" value="unknown" checked>不確定
</ul>
<input type="submit">
<input type="reset">
</form>
<hr>
<body>
</html>

由上述原始碼可看出,表單資訊傳送的方法是 get(這也是表單的 method 性質的預設值),當使用者按下「送出查詢」時,表單資料即由伺服器端的 getCgiParam.pl 來處理,回傳結果如下:

由上述回傳的網頁,可看出網址是「getCgiParam.pl?your_name=Roger+Jang&gender=unknown」,代表表單的相關資訊是附加在處理程式後面,再一起送到伺服器,這就是當 method 等於 get 時的作法。伺服器收到這一串資訊後,會將之儲存在名稱為 QUERY_STRING 的環境變數,然後再送交外部程式(在此為 getCgiParam.pl)進行處理。getCgiParam.pl 的原始碼如下:

原始檔(getCgiParam.pl):(灰色區域按兩下即可拷貝)
if ($ENV{"QUERY_STRING"} ne "") {
	$paramStr = $ENV{"QUERY_STRING"};			# method=get
	$method = "get";
} else {
	read(STDIN, $paramStr, $ENV{'CONTENT_LENGTH'});	# method=post
	$method = "post";
}

%FORM = &parseForm($paramStr);

print "Content-type: text/html\n\n";
@allkeys = sort keys %FORM;

print "<html><head><title>Form Elements</title><meta HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=big5\"></head>\n";
print "<body>\n";
print "<h2 align=center>CGI 如何傳遞及抽取參數(method=get)</h2>\n";
print "<hr>\n";
print "<h3>參數傳遞的方法:</h3>";
print "<blockquote><font color=green>$method</font></blockquote>\n";
print "<h3>CGI 收到的字串:</h3>";
print "<blockquote><font color=green>$paramStr</font></blockquote>\n";
print "<h3>抽取出來的資訊:</h3>";
print "<blockquote>\n";
for $key (@allkeys) {
	print "\$FORM(\"$key\") = <font color=green>$FORM{$key}</font><br>\n";
}
print "</blockquote></body></html>\n";

# Split the name-value pairs of a CGI parameter string
sub parseForm {
	my($parameter_string) = @_;
	my(%FORM);
	@pairs = split(/&/, $parameter_string);			# 根據 "&" 將 name-value pairs 拆解開來
	foreach $pair (@pairs) {				# 對每一個 name-value pair 進行處理
		($name, $value) = split(/=/, $pair);			# 抓出 name 和 value
		$value =~ tr/+/ /;				# 將 "+" 代換成空白
		$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/chr(hex($1))/eg;	# 將 %-encoding 解回原先的文字
		$FORM{$name} .= "#" if defined($FORM{$name});	# 若有重複的欄位,以 "#" 連結
		$FORM{$name} .= $value;			# 將結果儲存在 FORM 變數
	}
	return(%FORM);
}

在上述原始碼中,我們加了許多註解,以讓同學瞭解 Perl 如何拆解送進來的字串。

事實上,上述的程式碼可同時用於 method=get 和 method=post 兩種情況。下面這個範例(widget.htm),就是用同樣的 CGI 程式來猜解由 method=post 所送進來的字串:

Example(widget.htm):

此範例包含了所有常用到的表單元素,當使用者按下「送出查詢」時,表單資料即由伺服器端的 getCgiParam.pl 來處理。由於所用到的傳送方法是 post,因此 Perl 程式必須經由標準輸入來讀入參數字串,字串的長度則可由環境變數 CONTENT_LENGTH 取得。請各位同學自行試試看此範例!

以下是 get 和 post 這兩種參數傳送方式的對照表:

  Method=Get Method=Post
傳送方式 經由環境變數 QUERY_STRING 經由標準輸入(其長度可由環境變數 CONTENT_LENGTH 得知)
讀取方式 $paramStr = $ENV{"QUERY_STRING"}; read(STDIN, $paramStr, $ENV{'CONTENT_LENGTH'});
優點 彈性較大 字串長度限制較寬鬆
缺點 字串長度限制較嚴苛 彈性較小(有時也算是優點)


Perl